//
// Created by denglibin on 19-10-23.

/**
 * 当调用 pthread_join() 时，当前线程会处于阻塞状态，直到被调用的线程结束后，当前线程才会重新开始执行。当 pthread_join() 函数返回后，
 * 被调用线程才算真正意义上的结束，它的内存空间也会被释放（如果被调用线程是非分离的）。这里有三点需要注意：
被释放的内存空间仅仅是系统空间，你必须手动清除程序分配的空间，比如 malloc() 分配的空间。
一个线程只能被一个线程所连接。
被连接的线程必须是非分离的，否则连接会出错。

 所以可以看出pthread_join()有两种作用：
用于等待其他线程结束：当调用 pthread_join() 时，当前线程会处于阻塞状态，直到被调用的线程结束后，当前线程才会重新开始执行。
对线程的资源进行回收：如果一个线程是非分离的（默认情况下创建的线程都是非分离）并且没有对该线程使用 pthread_join() 的话，
 该线程结束后并不会释放其内存空间，这会导致该线程变成了“僵尸线程”。
 **/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

static void * t_fun(void * arg){
    int i = (int)arg;
    /* if(i == 1){
         pthread_exit(NULL); // 线程退出
     }*/
    printf("thread -- pid = %d, t_pid = %lu, i = %d\n", getpid(), pthread_self(), i);
    int * m = (int *)calloc(1, sizeof(int)); // 分配堆空间
    *m = i;
    return (void*)m;
}

static int main_(void){
    printf("main -- pid = %d, t_id = %lu\n", getpid(), pthread_self());
    pthread_t ts[3];
    for(int i = 0; i < 3; i++){
        int ret = pthread_create(ts+i, NULL, t_fun, (void *)i); // 创建线程
        if(ret != 0){
            fprintf(stderr, "pthread_create error:%s\n", strerror(ret));
            exit(-1);
        }
    }

    for(int i = 0; i < 3; i++){
        int * exit = NULL;
        int ret = pthread_join(ts[i], (void **)&exit); // 线程回收 阻塞 exit接收线程的返回值（返回值是指针）
        if(ret == 0){
            printf("join success t_id = %lu, result = %d\n", ts[i], *exit);
            free(exit);
        }
    }
    return 0;
}